package event

import (
	"context"
	"errors"
	"fmt"
	"gitee.com/simple-set/simple.io/src/socket"
)

type BootServer struct {
	*Event
	ctx     context.Context
	cancel  context.CancelFunc
	starter StarterServer
}

func NewBootServer() *BootServer {
	return NewBootServerContext(context.Background())
}

func NewBootServerContext(ctx context.Context) *BootServer {
	if ctx == nil {
		ctx = context.Background()
	}
	ctx, cancelFunc := context.WithCancel(ctx)
	return &BootServer{ctx: ctx, cancel: cancelFunc, Event: NewEvent()}
}

func (b *BootServer) CancelFunc() {
	if b.cancel != nil {
		b.cancel()
	}
}

func (b *BootServer) Starter() StarterServer {
	return b.starter
}

func (b *BootServer) Stop() error {
	if b.starter == nil {
		return errors.New("starter is nil")
	}
	return b.starter.Close()
}

// BindAddr 绑定监听地址, 如：localhost:8080, 0.0.0.0:8080, :8080, [::1]:0
func (b *BootServer) BindAddr(network string, addr string) error {
	var server socket.Server
	if network == "tcp" {
		server = socket.NewTcpServerContext(context.WithoutCancel(b.ctx), addr)
	} else if network == "udp" {
		server = socket.NewUdpServerContext(context.WithoutCancel(b.ctx), addr)
	} else {
		return fmt.Errorf("network not support %s", network)
	}

	if err := server.Bind(); err != nil {
		return err
	}
	b.starter = newStarterServer(server, b.Event, b.ctx)
	return nil
}

// ListenTcp 启动监听
func (b *BootServer) ListenTcp(addr string) error {
	if err := b.BindAddr("tcp", addr); err != nil {
		return err
	}
	return b.starter.Listen()
}

func (b *BootServer) ListenUdp(addr string) error {
	if err := b.BindAddr("udp", addr); err != nil {
		return err
	}
	return b.starter.Listen()
}
